/*
Pyxis 2.0
Copyright 2010-2011 Thomas W. Holtquist

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using System;
using System.IO;
using System.Text;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Presentation.Media;

using Skewworks.Pyxis.EXT;
using Skewworks.Pyxis.GUI.Controls;

namespace Skewworks.Pyxis.Kernel
{

    internal class DesktopIcon
    {

        #region Variables

        private string _file;
        private string _target;
        private int _x;
        private int _y;
        private string _title;
        private int _w;
        private int _h;
        private Image32 _image;
        private PyxisAPI API;
        private bool _mDown = false;
        private bool _visible = true;

        private TapState _eTapHold;                             // TapHold used to wait for ContextMenus
        private point _ptTapHold;

        #endregion

        #region Events

        public event OnTap tapEvent;

        /// <summary>
        /// Event for Taps
        /// </summary>
        /// <param name="sender"></param>
        protected virtual void OnTap(object sender, point e)
        {
            if (tapEvent != null) tapEvent(sender, e);
        }

        public event OnTapHold TapHold;

        /// <summary>
        /// Event for Tap & Hold
        /// </summary>
        /// <param name="sender"></param>
        protected virtual void OnTapHold(object sender, point e)
        {
            if (TapHold != null) TapHold(sender, e);
        }

        #endregion

        #region Constructor

        public DesktopIcon(PyxisAPI api, string sFile, int X, int Y, int Width, int Height, bool Visible)
        {
            byte[] Data;
            int lStart = 0;
            byte[] bTemp;

            // Read the file
            _file = sFile;
            FileStream iFile = new FileStream(sFile, FileMode.Open, FileAccess.Read);
            Data = new byte[new FileInfo(sFile).Length];
            iFile.Read(Data, 0, Data.Length);
            iFile.Close();

            // Get the target application
            bTemp = new byte[Data[0]];
            Array.Copy(Data, 1, bTemp, 0, bTemp.Length);
            _target = new string(Encoding.UTF8.GetChars(bTemp));

            // Get the link title
            lStart = bTemp.Length + 1;
            bTemp = new byte[Data[lStart]];
            Array.Copy(Data, lStart + 1, bTemp, 0, bTemp.Length);
            _title = new string(Encoding.UTF8.GetChars(bTemp));

            // Read the icon
            try
            {
                lStart += _title.Length + 1;
                bTemp = new byte[Data.Length - lStart];
                Array.Copy(Data, lStart, bTemp, 0, bTemp.Length);
                _image = new Image32(bTemp);
            }
            catch (Exception)
            {
                _image = new Image32(EmbeddedResourceManager.GetImage32BytesByName("Application"));
            }

            // Update variables
            _x = X;
            _y = Y;
            _w = Width;
            _h = Height;
            _visible = Visible;
            API = api;
        }

        public DesktopIcon(PyxisAPI api, string Title, string Target, byte[] Icon, int X, int Y, int Width, int Height, bool Visible)
        {
            _target = Target;
            _title = Title;
            _image = new Image32(Icon);
            _x = X;
            _y = Y;
            _w = Width;
            _h = Height;
            _visible = Visible;
            API = api;
        }

        #endregion

        #region Touch Invokes

        public void TouchDown(object sender, point e)
        {
            if (!_visible) 
                return;
            
            _mDown = true;

            // Begin TapHold
            _ptTapHold = e;
            _eTapHold = TapState.THWaiting;
            Thread thHold = new Thread(TapHoldWaiter);
            thHold.Start();
        }

        public void TouchUp(object sender, point e)
        {
            if (!_visible) return;

            // Check Tap Hold
            if (_eTapHold == TapState.THComplete)
            {
                _eTapHold = TapState.Normal;
                return;
            }

            _eTapHold = TapState.Normal;

            if (_mDown)
            {
                if (this.ScreenBounds.contains(e))
                    API.StartApplication(_target, _title, null);

                _mDown = false;
            }
        }

        public void TouchMove(object sender, point e)
        {
            // Do nothing
        }

        private void TapHoldWaiter()
        {
            Thread.Sleep(750);
            if (_eTapHold == TapState.Normal)
                return;

            OnTapHold(this, _ptTapHold);
        }

        #endregion

        #region Properties

        public string Filename
        {
            get { return _file; }
        }

        public Image32 Image
        {
            get { return _image; }
            set { _image = value; }
        }

        public rect ScreenBounds
        {
            get { return new rect(_x, _y, _w, _h); }
        }

        public bool PenDown
        {
            get { return _mDown; }
        }

        public string Target
        {
            get { return _target; }
        }

        public string Title
        {
            get { return _title; }
        }

        public bool Visible
        {
            get { return _visible; }
            set { _visible = value; }
        }

        #endregion

        #region GUI

        public void Render()
        {
            if (!_visible) return;

            int w, h;
            int offset = 0;

            if (_image != null)
                _image.draw(API.ScreenBuffer, _x + ((_w / 2) - (_image.Width / 2)), _y);

            FontManager.Arial.ComputeTextInRect(_title, out w, out h, _w - 4);
            w += 4;
            h += 4;

            if (h > _h - 35) h = _h - 35;

            offset = (_w / 2) - (w / 2);

            API.ScreenBuffer.DrawRectangle(Color.Black, 0, _x + offset, _y + 36, w, h, 0, 0, Color.Black, 0, 0, Color.Black, 0, 0, 150);
            API.ScreenBuffer.DrawTextInRect(_title, _x + 2 + offset, _y + 38, w - 4, h - 4, Bitmap.DT_WordWrap + Bitmap.DT_AlignmentCenter, Color.White, FontManager.Arial);

        }

        #endregion

    }
}
